//
//  QRCodeViewController.swift
//  Super_WeiBo
//
//  Created by 梁超 on 16/3/17.
//  Copyright © 2016年 lc. All rights reserved.
//

import UIKit
import AVFoundation

class QRCodeViewController: UIViewController , UITabBarDelegate{

    // 左侧关闭按钮
    @IBAction func colseBtn(sender: AnyObject) {
        dismissViewControllerAnimated(true, completion: nil)
    }
    // 右侧相册按钮
    @IBAction func photoBtn(sender: AnyObject) {
        
        // 判断相册是否可以打开
        let isOpen = UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary)
        if !isOpen
        {
            return
        }
        // 创建图片选择控制器
        let ipVC = UIImagePickerController()
        ipVC.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
        // 设置代理
        ipVC.delegate = self
        // modal出控制器
        presentViewController(ipVC, animated: true, completion: nil)
        
    }
    
    /// 扫描波
    @IBOutlet weak var scanView: UIImageView!
    /// 扫描波顶部约束
    @IBOutlet weak var scanTopCons: NSLayoutConstraint!
    /// 容器高度
    @IBOutlet weak var containerHeightCons: NSLayoutConstraint!
    /// 底部tabBar
    @IBOutlet weak var customTabBar: UITabBar!
    ///  显示扫描内容
    @IBOutlet weak var infoLabel: UILabel!
    /// 扫描区域打底
    @IBOutlet weak var contenView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        customTabBar.delegate = self
        // 设置默认选中第0个按钮
        customTabBar.selectedItem = customTabBar.items![0]
    }
    
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        // 开始动画
//        startAnimation()
        
        // 开始扫描
        startScan()
    }
    
    /**
     扫描二维码
     */
    private func startScan()
    {
        // 判断是否能够将输入添加到回话中
        if !session.canAddInput(deviceInput)
        {
            return
        }
        // 判断是否能够将输出添加到回话中
        if !session.canAddOutput(deviceOutput)
        {
            return
        }
        // 将输入、输出添加到会话中
        session.addInput(deviceInput)
        session.addOutput(deviceOutput)
        // 设置输出能够解析的类型
        deviceOutput.metadataObjectTypes = deviceOutput.availableMetadataObjectTypes
        // 设置输出对象代理，只要解析成功就会通知代理
        deviceOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        // 计算扫描区域
        deviceOutput.rectOfInterest = outputViewFrame()
        // 添加预览图层
        view.layer.insertSublayer(preiewLayer, atIndex: 0)
        // 将绘制图层添加到预览图层上
        preiewLayer.addSublayer(drawLayer)
        // 高速 会话 开始扫描
        session.startRunning()
    }
    
    private func outputViewFrame() -> CGRect
    {
        // 获取屏幕的frame
        let viewRect = UIScreen.mainScreen().bounds
        // 获取扫描容器的frame
        let containerRect = contenView.frame
        // 计算捕获二维码区域
        // 向左倒横屏 左上角为(0,0)点
        // (x, y, width, height) 这四个元素，计算的是扫描区域和父视图的比例关系
        // 因为是横屏使用 x-y 互换
        let x = (viewRect.size.height - containerRect.size.height)/2 / viewRect.size.height
        let y = (viewRect.size.width - containerRect.size.width)/2  / viewRect.size.width
        let width = containerRect.size.height / viewRect.size.height
        let height = containerRect.size.width / viewRect.size.width
        return CGRectMake(x, y, width, height)
    }
    
    // MARK: - UITabBarDelegate
    func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
        
        if item.tag == 1{
            // 二维码
            containerHeightCons.constant = 300
        }else{
            // 条形码
            containerHeightCons.constant = 150
        }
        // 切换是停止动画
        scanView.layer.removeAllAnimations()
        // 重新开始动画
//        startAnimation()
    }
    
    /**
     执行动画
     */
    func startAnimation ()
    {
        // 让约束从顶部开始
        self.scanTopCons.constant = -self.containerHeightCons.constant
        // 更改约束后必须强制更新
        self.scanView.layoutIfNeeded()
        
        // 执行扫描动画
        UIView.animateWithDuration(1.0, animations: { () -> Void in
            // 修改约束
            self.scanTopCons.constant = self.containerHeightCons.constant
            // 设置循环次数
            UIView.setAnimationRepeatCount(MAXFLOAT)
            // 强制更新
            self.scanView.layoutIfNeeded()
            })
    }
    // MARK: - 懒加载
    // 会话
    private lazy var session : AVCaptureSession = AVCaptureSession()
    
    // 拿到输入设备
    private lazy var deviceInput : AVCaptureInput? = {
       
        // 获取摄像头
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        do{
            let input = try AVCaptureDeviceInput(device: device)
            return input
        }catch{
            print(error)
            return nil
        }
    }()
    
    // 拿到输出设备
    private lazy var deviceOutput : AVCaptureMetadataOutput = AVCaptureMetadataOutput()
    
    // 创建预览图层
    private lazy var preiewLayer : AVCaptureVideoPreviewLayer = {
        let lary = AVCaptureVideoPreviewLayer(session: self.session)
        lary.frame = UIScreen.mainScreen().bounds
        return lary
    }()
    
    // 用于绘制的图层
    private lazy var drawLayer : CALayer = {
        let layer = CALayer()
        layer.frame = UIScreen.mainScreen().bounds
        return layer
    }()
    
    
}
// MARK: - UIImagePickerControllerDelegate
extension QRCodeViewController : UIImagePickerControllerDelegate, UINavigationControllerDelegate
{
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
    {
        // 取出选中的图片
        let pickImage = info[UIImagePickerControllerOriginalImage] as! UIImage
        let ciImage = CIImage(image: pickImage)
        
        // 从选中的图片中读取二维码数据
        // 创建一个探测器
        let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyLow])
        
        // 利用探测器探测数据
        let feature = detector.featuresInImage(ciImage!)
        
        // 取出探测到的数据
        for result in feature
        {
            let urlStr = (result as!CIQRCodeFeature).messageString
            // 展示二维码内信息
            infoLabel.text = urlStr
        }
        
        // 关闭相册控制器
        dismissViewControllerAnimated(true, completion: nil)
    }
}
extension QRCodeViewController : AVCaptureMetadataOutputObjectsDelegate
{
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!)
    {
        // 展示二维码内信息
        infoLabel.text = metadataObjects.last?.stringValue
        // 转换坐标
        for object in metadataObjects
        {
            // 判断数据是否未机器可识别
            if object is AVMetadataMachineReadableCodeObject
            {
                let codeObject = preiewLayer.transformedMetadataObjectForMetadataObject(object as! AVMetadataObject) as! AVMetadataMachineReadableCodeObject
                // 绘制轮廓
                drawCorners(codeObject)
            }
        }
    }
    // 绘制图形
    private func drawCorners(codeObject : AVMetadataMachineReadableCodeObject)
    {
        // 绘制图形之前先清空之前的
        clearConers()
        
        // 判断坐标数组是否为空
        if codeObject.corners.isEmpty
        {
            return
        }
        // 创建图层
        let layer = CAShapeLayer()
        layer.lineWidth = 4
        layer.fillColor = UIColor.clearColor().CGColor
        
        layer.strokeColor = UIColor.cyanColor().CGColor
        
        // 创建路径
        let path = UIBezierPath() // 绘制路径
        var point = CGPointZero // 保存点
        var index : Int = 0
        
        // 取出数组中的第零个点
        CGPointMakeWithDictionaryRepresentation((codeObject.corners[index++] as! CFDictionaryRef), &point)
        // 画第一个点
        path.moveToPoint(point)
        // 画其余三个点
        while index < codeObject.corners.count
        {
            CGPointMakeWithDictionaryRepresentation((codeObject.corners[index++] as! CFDictionaryRef), &point)
            path.addLineToPoint(point)
        }
        // 关闭路径
        path.closePath()
        // 绘制路径
        layer.path = path.CGPath
        // 将绘制好的图层添加到 drawLayer 图层上
        drawLayer.addSublayer(layer)
    }
    
    // 清空上次绘制的图层
    private func clearConers(){
        if drawLayer.sublayers == nil || drawLayer.sublayers?.count == 0
        {
            return
        }
        
        for sublayer in drawLayer.sublayers!
        {
            sublayer.removeFromSuperlayer()
        }
    }
}







